package pdi.core;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.text.StrBuilder;
import org.opencv.core.Mat;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;

import pdi.OpenCvCaller;

import utils.IConstants;

public class Image {

	private Mat matrixRepresentation;
	private String name;
	private int width;
	private int height;
	private String path;
	private double[] featureVector;
	private List<BoundingBox> groundTruth ;

	public Image() {}

	public Image(String imgPath, String annotationPath , double[] featureVector) throws IOException {

		this.setMatrixRepresentation(OpenCvCaller.getInstance().readImage(imgPath));
		this.width = matrixRepresentation.width();
		this.height = matrixRepresentation.height();
		this.setName(Paths.get(imgPath).getFileName().toString());
		this.setPath(imgPath);

		this.groundTruth = BoundingBox.readFile(annotationPath);
		this.featureVector = featureVector;

	}
	public Image(String imgPath, String annotationPath) throws IOException{
		this(imgPath, annotationPath,null);		
	}

	public Image(String path) throws IOException {
		this(path,null,null);
	}

	public Image(String imgPath, double[] featureVector) throws IOException {
		this(imgPath, null, featureVector);		
	}		

	public void save(String filePath){
		OpenCvCaller.getInstance().writeImage(filePath, matrixRepresentation);
	}

	public void flushMatrixRepresentation(){
		this.matrixRepresentation = null;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	public double[] getFeatureVector() {
		return featureVector;
	}
	public void setFeatureVector(double[] featureVector) {
		this.featureVector = featureVector;
	}
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
	public Mat getMatrixRepresentation() {
		return matrixRepresentation;
	}
	public void setMatrixRepresentation(Mat matrixRepresentation) {
		this.matrixRepresentation = matrixRepresentation;
	}


	@Override
	public String toString() {
		StrBuilder b = new StrBuilder();

		b.appendln("Image: " + name + " ,path = " + path);
		b.appendln("matrixRepresentation: " + (matrixRepresentation!= null ? matrixRepresentation.toString() : "null"));
		b.appendln("width = " + width + " height = " + height);
		b.appendln("number of pedestrian: " + countBB(IConstants.PERSON));
		b.appendln("featureVector = " + Arrays.toString(featureVector));


		return  b.toString();
	}

	public int countBB(int label){
		int count = 0;
		if(this.groundTruth != null && this.groundTruth.size() > 0){
			for (BoundingBox bb : this.groundTruth) {
				if(bb.getLabel() == label)
					count ++;
			}
		}
		return count;			
	}

	@Override
	public Image clone() {
		Image clone = new Image();
		clone.setName(this.getName());
		clone.setPath(this.getPath());
		clone.setHeight(this.getHeight());
		clone.setWidth(this.getWidth());

		if(this.groundTruth != null && this.groundTruth.size() > 0)
			clone.setGroundTruth(this.groundTruth);

		if(this.matrixRepresentation != null)
			clone.setMatrixRepresentation(this.matrixRepresentation.clone());

		if(this.featureVector != null)
			clone.setFeatureVector(ArrayUtils.clone(this.featureVector));

		return clone;
	}


	public List<BoundingBox> getGroundTruth() {
		return groundTruth;
	}


	public void setGroundTruth(List<BoundingBox> groundTruth) {
		this.groundTruth = groundTruth;
	}


}
